﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;
using System.Net.Sockets;
using System.Xml;
using AgilePlannerDT.Data;
using AgilePlannerDT.Data.Impl;

namespace AgilePlannerDT.Persister.Impl.Socket
{
    public class InboundConnection
    {
        IConnection connection;
        XMLSocketClient client;
        Boolean close;
        

        public InboundConnection(IConnection connection, XMLSocketClient client)
        {
            close = false;
            this.connection = connection;
            this.client = client;
        }

        byte[] readMessage(Stream stream, int expectedLength)
        {
            int offset = 0;
            byte[] ret = new byte[expectedLength];
            while ((offset += stream.Read(ret, offset, expectedLength)) < expectedLength)
            {
                // we yeild the cpu here to prevent this loop 
                // from being an INFINITE pain in the ass.
                System.Threading.Thread.Sleep(0);
            }
            return ret;
        }

        private int byteArrayToInt(byte[] b)
        {
            return (b[4] & 0xff) << 24 | (b[5] & 0xff) << 16 | (b[6] & 0xff) << 8 | (b[7] & 0xff);
        }

        int getNextMessageLength(Stream stream)
        {
            return byteArrayToInt(readMessage(stream, 8));
        }

        public void Listen()
        {
            while (!close)
            {
                String xml = "";
                try
                {
                    int length = byte2int(connection.read(8));
                    if (length > 0)
                    {
                        byte[] message = connection.read(length);
                        xml = Encoding.UTF8.GetString(message);
                        Message receivedMessage = new MessageDataObject(MessageDataObject.RAW_MESSAGE);
                        receivedMessage.ReadXml(xml);
                        client.Receive(receivedMessage);
                    }
                    else
                    {
                        continue;
                    }
                }
                catch (IOException)
                {
                    this.Stop();
                }
                catch (XmlException e1)
                {

                }
                catch (Exception e)
                {
                    System.Windows.MessageBox.Show("\"" + xml + "\"" + "\n\n" + e.Message + "\n" + e.StackTrace);
                    throw e;
                }
            }
        }
        public void Stop()
        {
            this.close = true;
        }

        private int byte2int(byte[] num)
        {
            if (num.Length != 8)
                throw new Exception("byte array is not size 8");
            int ret = 0;
            for (int i = 0; i < 8; i++)
            {
                ret += num[i];
                if (i != 7) ret <<= 8;
            }
            return ret;
        }
    }



}
